The C++ compiler invokes virtual functions correctly--except when a non-virtual function is redeclared as virtual in a subclass. The compiler issues a warning in this case, however.
In this example, the function f() in class Animal is redeclared virtual in the subclass Mammal :
class Animal { void f(); }
class Mammal : public virtual Animal { virtual void f(); }
class Quadruped : public virtual Animal { virtual void f(); }
class Dog : public Mammal, public Quadruped { virtual void f(); }
class Terrier : public Dog { virtual void f(); }
Invoking the method f() gives the wrong result in the following case:
void zoo(void) {
Terrier* terrier = new Terrier;
Mammal* mammal = terrier;
Quadruped* quadruped = terrier;
Dog* dog = terrier;
quadruped->f(); // Wrong - invokes Dog::f()
mammal->f(); // Right - invokes Terrier::f()
dog->f(); // Right - invokes Terrier::f()
}
The compiler warns that wrong code may be generated:
warning: method `Animal::f()' redeclared as `virtual Mammal::f()'
If you modify the above hierarchy by making the function f() in Animal virtual, the invocation works correctly. The workaround is therefore to make f() virtual throughout the hierarchy:
class Animal { virtual void f(); }
class Mammal : public virtual Animal { virtual void f(); }
class Quadruped : public virtual Animal { virtual void f(); }
class Dog : public Mammal, public Quadruped { virtual void f(); }
class Terrier : public Dog { virtual void f(); }